package com.kaede.game.netty;

import com.google.protobuf.MessageLite;
import io.netty.channel.*;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;

/**
 * 代码清单 11-14 使用 protobuf
 *
 * @author <a href="mailto:norman.maurer@gmail.com">Norman Maurer</a>
 */
public class ProtoBufInitializer extends ChannelInitializer<Channel> {

    private final MessageLite lite;

    private int maxFrameLength;

    private int lengthFieldOffset;

    private int lengthFieldLength;

    private int lengthAdjustment;

    private int initialBytesToStrip;

    private ChannelInboundHandler channelInboundHandler;

    public ProtoBufInitializer(ChannelInboundHandler channelInboundHandler, MessageLite lite, int maxFrameLength, int lengthFieldOffset,
                               int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip) {
        this.lite = lite;
        this.channelInboundHandler = channelInboundHandler;
        this.maxFrameLength = maxFrameLength;
        this.lengthFieldOffset = lengthFieldOffset;
        this.lengthFieldLength = lengthFieldLength;
        this.lengthAdjustment = lengthAdjustment;
        this.initialBytesToStrip = initialBytesToStrip;
    }

    @Override
    protected void initChannel(Channel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        //添加 LengthFieldBasedFrameDecoder 以分隔帧
        pipeline.addLast(new LengthFieldBasedFrameDecoder(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip));
//        pipeline.addLast(new ProtobufVarint32FrameDecoder());
        //添加 ProtobufDecoder 以解码消息
        pipeline.addLast(new ProtobufDecoder(lite));
        //添加 LengthFieldPrepender 以分隔返回帧
        pipeline.addLast(new LengthFieldPrepender(lengthFieldLength));
//        pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
        //添加 ProtobufEncoder 以处理消息的编码
        pipeline.addLast(new ProtobufEncoder());
        //添加 自定义Handler 以处理解码消息
        pipeline.addLast(channelInboundHandler);
    }
}
